/*
    This is a set of libraries to assist in OpenGl and Other Applications
    Copyright (C) 2008  The Modular Engine Team

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/// \file GraphicsModule.h
/// \brief Contains base classes for Graphics Library and basic graphics functions


#ifndef GRAPHICSMODULE_H
#define GRAPHICSMODULE_H

#include "OpenglInterface.h"
#include "math.h"
#include "EngineCore.h"
#include "ImageLoader.h"

#include <fstream>
#include <list>
#include <sstream>
#include <string>

using namespace std;

#undef CLASSDECL
#ifdef GRAPHICSMODULE
	#define CLASSDECL __declspec(dllexport)
#else
	#pragma comment( lib, "GraphicsModule.lib" )
	#define CLASSDECL __declspec(dllimport)
#endif

namespace ModularEngine
{
	/// Contains functions to load fonts and corresponding width file

	/// BitmapFont holds information for properly displaying Bitmap-based fonts
	/// to the screen.
	class CLASSDECL BitmapFont
	{
	private:
		/// Table containing the individaul character widths

		/// These correspond with the texture holding the font
		/// table
		char cWidths[256];
		
	public:
		
		/// Sets the tracking and leading to one.
		BitmapFont();

		/// Tracking based on a proportion.

		/// Tracking is the amount of space between letters.
		/// By default this should be zero, but if more (or less) space
		/// is wanted, this proportion can be modified to change as such.
		float mfTrackingProp;

		/// Leading based on a proporation

		/// Leading is the amount of vertical space between lines.  If your 
		/// lines are too far apart adjust this value.
		float mfLeadingProp;

		/// Font texture and properties
		TextureID tFontTexture;
		/// Load Bitmap Font From File

		/// Uses the ImageLoader.
		int loadFont( const char *pFontPath );

		/// Load Font Widths from file.

		/// Font widths only supported in binary byte file.
		int loadFontWidths( const char *pFontWidthsPath );

		// Load Font Widths file and Texture at same time
		int loadFontFull( const char *pFontName, float tracking = 1, float leading = 1 );

		/// Returns the texture to the caller
		unsigned int returnTexture()
		{
			return tFontTexture.mTexNum;
		}

		/// Returns the width of the specified character
		char charWidth(char cWhich)
		{
			return cWidths[cWhich];
		}

		/// Returns the X,Y dimensions on the texture to 
		/// The character
		Vector2d charPlace(char cWhich);
	};

	/// Responsible for drawring text to the screen.
	
	/// Yes, I meant drawring. 
	class CLASSDECL TextEngine
	{
	protected:
		/// Default font to be used by this engine
		BitmapFont mbDefaultFont;
		/// Default font height to be used by this engine
		int mnDefaultHeight;
		/// Default bounds to cut off the text to be used by this engine.
		Vector2d mvDefaultBounds[2];

	public:
		/// Draw singleline of text to screen using bFont
		void drawText( BitmapFont bFont, int height, const char *pText, Vector2d vPos, Vector2d vBounds[2] );
		void drawText( const char *pText, Vector2d vPos );
		void drawText( const char *pText, Vector2d vPos, Vector2d vBounds[2] ); //, Vector2d vBounds[2] = mvDefaultBounds, int height = mnDefaultHeight, BitmapFont bFont = mbDefaultFont );

		/// Draw lines of text to the screen. 
		/// Text passed to this should be preprocessed by processMultiline()
		void drawTextMultiline( BitmapFont bFont, int height, vector<string> *lines, Vector2d vPos, Vector2d vBounds[2] );

		/// Returns the processed multiline data to be sent to drawTextMultiline()
		vector<string> *processMultiline( BitmapFont bFont, int height, const char *pText, int maxWidth );

		/// Converts a long string into a "vector" of words seperated by spaces or newlines.
		vector<string> *makeWords( const char *pText );

		/// Returns the width of a word based on the BitmapFont settings and height
		int wordSize(BitmapFont bFont, int nHeight, string sWord);


	};


// For The Time Being We're Going to Use the OpenglInterface directly, then add this once
// It's done so we can port to other interfaces.
// Overall,  this is done primarily to simplify the creation of the OpenglInterface
#if USING_GRAPHICS_INTERFACE_BASE

	/// Graphics Interface Options and States
	enum GI_OPTIONS
	{
		GI_TEXTURE = 0,
		GI_DEPTH_BUFFER_BIT,
		GI_COLOR_BUFFER_BIT,
		GI_POINTS,
		GI_LINES,
		GI_LINE_STRIP,
		GI_TRANGLES,
		GI_TRANGLE_STRIP,
		GI_TRANGLE_FAN,
		GI_QUADS,
		GI_QUAD_STRIP,
		GI_POLYGON
	};


	/// Base for independent graphics library.

	/// This will be the base for graphics library
	/// independent code.  
	/// In other words, the basic graphics calls will be
	/// abstracted and interpreted by the individual graphics libraries.
	/// To use Opengl, an Opengl graphics interface must be made using 
	/// GraphicsInterfaceBase as it's parent.
	class GraphicsInterfaceBase
	{
	protected:
		std::list<TextureID> mlTextures;
	public:
		virtual void init() = 0;

		/// Bind Textnum to current texture context
		virtual void bindTexture( unsigned int nTex ) = 0;

		/// Err... stuff 
		virtual TextureID *loadTexture(const char *pTexturePath, const char *pMacro=0) = 0;

		/// Draw Image
		virtual void drawImage( const char *pTexturePath, Vector2d vPos ) = 0;

		/// Draw Regular, untextured quad
		virtual void drawQuad( Vector2d vPos, Vector2d vDims ) = 0;
		/// Draw Textured Quad Using Entire Texture
		virtual void drawQuad( unsigned int nTexture, Vector2d vPos, Vector2d vDims ) = 0;
		/// Draw Textured Quad Using Texture Coordinates
		virtual void drawQuad( unsigned int nTexture, Vector2d vTexCoords[2], Vector2d vPos, Vector2d vDims ) = 0;

		/// Start Drawing

		/// iState refers to what we're drawing, be it lines, polygons etc.
		virtual void startDrawing( unsigned int iState ) = 0;

		/// Stop Drawing
		virtual void stopDrawing() = 0;

		/// Enable something such as textures or lighting.
		virtual void enable( unsigned int iState ) = 0;

		/// Disable something...
		virtual void disable( unsigned int iState ) = 0;

		/// Set current texture
		virtual void setTexture( unsigned int iTextureID ) = 0;
	};
#endif // #if USING_GRAPHICS_INTERFACE_BASE

	/// This will take care of drawing everything everytime
	class CLASSDECL GraphicsModule: BASE(GraphicsModule)
	{
	public:
		/// Graphics Interface Pointer from which "Everything" should be drawn
		OpenglInterface *gI;

		int initialize();
		int run();

	};

}

#endif